package com.hulk.rpc.loadbalance;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.hulk.rpc.exception.HulkRpcException;
import com.hulk.rpc.loadbalance.impl.*;
import lombok.AllArgsConstructor;

import java.util.List;

/**
 * @author xuxukang
 * @date 2019-03-26 23:14
 */
public abstract class LoadBalance<T extends Weightable> {

  protected List<T> resources = Lists.newArrayList();

  /**
   * 选择一个资源
   */
  public abstract T select();

  /**
   * refresh之后清除以前的select相关的变量信息
   */
  public abstract void clean();

  /**
   * 初始化路由资源、或动态重加载最新的路由资源
   *
   * @param refreshResources 某app最新的激活的连接资源
   */
  public void refreshResources(List<T> refreshResources) {
    if (CollUtil.isEmpty(refreshResources)) {
      return;
    }
    resources.clear();
    CollUtil.addAll(resources, refreshResources);
    clean();
  }

  @AllArgsConstructor
  public enum LoadBalanceEnum {
    /**
     * 负载均衡策略工厂
     */
    consistent_hash(ConsistentHashLoadBalance.class),
    random(RandomLoadBalance.class),
    round_robin(RoundRobinLoadBalance.class),
    weight_random(WeightRandomLoadBalance.class),
    weight_round_robin(WeightRoundRobinBalance.class);

    private Class<? extends LoadBalance> loadBalanceClass;

    public LoadBalance getLoadBalance() {
      try {
        return loadBalanceClass.getDeclaredConstructor().newInstance();
      } catch (Exception e) {
        throw new HulkRpcException(e);
      }
    }

    public static LoadBalanceEnum getMatchedBalance(String name, LoadBalanceEnum defaultEnum) {
      for (LoadBalanceEnum value : LoadBalanceEnum.values()) {
        if (value.name().equalsIgnoreCase(name)) {
          return value;
        }
      }
      return defaultEnum;
    }
  }

}
